﻿////测试文件
//#include "sdftest1.h"
//#include <stdlib.h>
//#include <string.h>
//#include <stdio.h>
//#include "openssl/ssl.h"
//#include <iostream>
//#pragma warning(disable:4996)
//#include "util.h"
//
//int main() {
//	void ** pdh;
//	void* hsh;
//	int open,session,ret;
//	int i;
//	unsigned char* pcR;
//	unsigned int* hex;
//	DEVICEINFO *dev;
//	//创建设备信息
//	dev = (DEVICEINFO*)malloc(sizeof(DEVICEINFO));
//	strcpy((char*)(*dev).IssuerName, "LYMFC");
//	strcpy((char*)(*dev).DeviceName, "LMGM001");
//	strcpy((char*)(*dev).DeviceSerial, "2021042200112345");
//	(*dev).DeviceVersion = 0000;
//	(*dev).StandardVersion = 0000;
//	//(*dev).AsymAlgAbility = 11;
//	(*dev).SymAlgAbility = 0000;
//	(*dev).HashAlgAbility = 0000;
//	(*dev).BufferSize = 6666;
//	//设备定义结束
//
//	pdh=(void **) malloc(20);
//	hsh = (void*)malloc(20);
//	open = SDF_OpenDevice(pdh);//连接设备
//	if (!open)
//	{
//		session = SDF_OpenSession(hsh, pdh);//创建会话
//	if (!session)
//		{
//			SDF_GetDeviceInfo(hsh, dev);//读取设备信息
//		}
//	}
//	pcR = (unsigned char *)malloc((20+3)*4);
//	hex = (unsigned int*)malloc(100);
//	ret=SDF_GenerateRandom(hsh, 20, pcR);
//	if (!ret)
//	{
//		/*for ( i = 0; i < 10; i++)
//		{
//			printf("%d\n", pcR[i]);
//		}*/
//		puts((char*)pcR);
//		printf("随机数OK");
//	}
//}
//
//
//
#include <stdio.h>
#pragma warning(disable:4996)
#include <string.h>
#include <windows.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#define FALSE 0
#define TRUE 1

typedef struct evp_cipher_ctx_st
{
	const EVP_CIPHER* cipher;  //是该结构相关的一个EVP_CIPHER算法结构
	ENGINE* engine;            //如果加密算法是ENGINE提供的，那么该成员保存了相关的函数接口
	int encrypt;               //加密或解密的标志
	int buf_len;               //该结构缓冲区里面当前的数据长度
	unsigned char oiv[EVP_MAX_IV_LENGTH];      //初始的初始化向量
	unsigned char iv[EVP_MAX_IV_LENGTH];       //工作时候使用的初始化向量
	unsigned char buf[EVP_MAX_BLOCK_LENGTH];   //保存下来的部分需要数据
	int num;                   //在cfb/ofb模式的时候指定块长度
	void* app_data;            //应用程序要处理数据
	int key_len;               //密钥长度，算法不一样长度也不一样
	unsigned long flags;
	void* cipher_data;         //加密后的数据
	int final_used;
	int block_mask;
	unsigned char final[EVP_MAX_BLOCK_LENGTH];//
} EVP_CIPHER_CTX;

//加密函数
int Encrypt_File()
{

	unsigned char key[EVP_MAX_KEY_LENGTH]; //保存密钥的数组
	unsigned char iv[EVP_MAX_KEY_LENGTH]; //保存初始化向量的数组
	EVP_CIPHER_CTX ctx; //EVP加密上下文环境
	unsigned char out[1024]; //保存密文的缓冲区
	int outl;
	unsigned char in[1024]; //保存原文的缓冲区
	int inl;
	int rv;
	int i;
	FILE* fpIn;
	FILE* fpOut;
	//打开待加密文件
	fpIn = fopen("所有同学的8位学号.txt", "rb");
	if (fpIn == NULL)
	{
		return FALSE;
	}
	//打开保存密文的文件
	fpOut = fopen("mikejmw.txt", "wb");
	if (fpOut == NULL)
	{
		fclose(fpIn);
		return FALSE;
	}
	//设置key和iv
	for (i = 0; i < 24; i++)
	{
		key[i] = i;
	}
	for (i = 0; i < 8; i++)
	{
		iv[i] = i;
	}

	//初始化ctx
	EVP_CIPHER_CTX_init(&ctx);
	//设置密码算法、key和iv
	rv = EVP_EncryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, key, iv);
	if (rv != 1)
	{
		printf("Err\n");
		return FALSE;
	}
	//循环读取原文，加密后后保存到密文文件。
	for (;;)
	{
		inl = fread(in, 1, 1024, fpIn);
		if (inl <= 0)//读取原文结束
			break;
		rv = EVP_EncryptUpdate(&ctx, out, &outl, in, inl);//加密
		if (rv != 1)
		{
			fclose(fpIn);
			fclose(fpOut);
			EVP_CIPHER_CTX_cleanup(&ctx);
			return FALSE;
		}
		fwrite(out, 1, outl, fpOut);//保存密文到文件
	}
	//加密结束
	rv = EVP_EncryptFinal_ex(&ctx, out, &outl);
	if (rv != 1)
	{
		fclose(fpIn);
		fclose(fpOut);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return FALSE;
	}
	fwrite(out, 1, outl, fpOut); //保密密文到文件
	fclose(fpIn);
	fclose(fpOut);
	EVP_CIPHER_CTX_cleanup(&ctx); //清除EVP加密上下文环境
	printf("加密已完成\n");
	return TRUE;
}


//解密函数
int Decrypt_File()
{
	unsigned char key[EVP_MAX_KEY_LENGTH]; //保存密钥的数组
	unsigned char iv[EVP_MAX_KEY_LENGTH]; //保存初始化向量的数组
	EVP_CIPHER_CTX ctx; //EVP加密上下文环境
	unsigned char out[1024 + EVP_MAX_KEY_LENGTH]; //保存解密后明文的缓冲区数组
	int outl;
	unsigned char in[1024]; //保存密文数据的数组
	int inl;
	int rv;
	int i;
	FILE* fpIn;
	FILE* fpOut;

	//打开待解密的密文文件
	fpIn = fopen("mikejmw.txt", "rb");
	if (fpIn == NULL)
	{
		return FALSE;
	}
	//打开保存明文的文件
	fpOut = fopen("mikejout.txt", "wb");
	if (fpOut == NULL)
	{
		fclose(fpIn);
		return FALSE;
	}
	//设置key和iv
	for (i = 0; i < 24; i++)
	{
		key[i] = i;
	}
	for (i = 0; i < 8; i++)
	{
		iv[i] = i;
	}

	//初始化ctx
	EVP_CIPHER_CTX_init(&ctx);
	//设置解密的算法、key和iv
	rv = EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, key, iv);
	if (rv != 1)
	{
		EVP_CIPHER_CTX_cleanup(&ctx);
		return FALSE;
	}
	//循环读取原文，解密后后保存到明文文件。
	for (;;)
	{
		inl = fread(in, 1, 1024, fpIn);
		if (inl <= 0)
			break;
		rv = EVP_DecryptUpdate(&ctx, out, &outl, in, inl);//解密
		if (rv != 1)
		{
			fclose(fpIn);
			fclose(fpOut);
			EVP_CIPHER_CTX_cleanup(&ctx);
			return FALSE;
		}
		fwrite(out, 1, outl, fpOut);//保存明文到文件
	}
	//解密结束
	rv = EVP_DecryptFinal_ex(&ctx, out, &outl);
	if (rv != 1)
	{
		fclose(fpIn);
		fclose(fpOut);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return FALSE;
	}
	fwrite(out, 1, outl, fpOut);//保存明文到文件
	fclose(fpIn);
	fclose(fpOut);
	EVP_CIPHER_CTX_cleanup(&ctx);//清除EVP加密上下文环境 
	printf("解密已完成\n");
	return TRUE;
}


int main()
{
	int i;
	int j;
	OpenSSL_add_all_algorithms();

	printf("|-------请您选择的服务类型--------|\n");
	printf("|                                 |\n");
	printf("|    1:加密   2:解密   3:退出     |\n");
	printf("|                                 |\n");
	printf("|---------------------------------|\n");
	printf("请输入选择:");
	scanf("%d", &i);
	for (j = 0; j < 50000000; j++)
	{
		if (j % 660000 == 0)
			printf(">");  //实现缓冲的功能
	}
	system("cls");
	switch (i)
	{
	case 1: Encrypt_File(); break;
	case 2: Decrypt_File(); break;
	case 3: exit(0); break;
	default:
		printf("         输入错误,请重新输入");
	}

	return 0;
}

